package org.app.appjson.writer;

import org.app.appjson.adapter.*;
import org.app.appjson.exception.AppJsonException;

import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Map;

/**
 * 写处理器
 * 递归调用本类的doWrite(Class<?> classOfT)方法操作本类，最终返回json字符串。
 * @author lizhongsi
 * @version 1.0
 * @since 1.0
 */
public class WriteHandler {

    private final Writer writer;

    // 用户传入的对象
    private Object object;

    public WriteHandler(Writer writer, Object object) {
        this.writer = writer;
        this.object = object;
    }

    /* 向writer写入字符串 */
    public void write(String s) throws AppJsonException {
        try {
            this.writer.write(s);
        } catch (IOException e) {
            throw new AppJsonException("write error：" + s);
        }
    }

    public Object getObject() {
        return this.object;
    }

    /**
     * 这里原本是返回"实现了Adapter接口的某个对象"，再调用对象的write方法
     * 最终写成静态方法是为了节省创建adapter对象的内存开销
     * @param object 对象
     */
    public void doWrite(Object object) throws AppJsonException {
        this.object = object;
        if (object == null) {
            this.write("null");
            return;
        }
        Class<?> classOfT = object.getClass();
        if (classOfT.isArray()) {
            ArrayAdapter.write(this);
        } else if (Boolean.class.isAssignableFrom(classOfT) || boolean.class.isAssignableFrom(classOfT)) {
            BooleanAdapter.write(this);
        } else if(byte.class.isAssignableFrom(classOfT) || Byte.class.isAssignableFrom(classOfT)) {
            ByteAdapter.write(this);
        } else if(short.class.isAssignableFrom(classOfT) || Short.class.isAssignableFrom(classOfT)) {
            ShortAdapter.write(this);
        } else if(int.class.isAssignableFrom(classOfT) || Integer.class.isAssignableFrom(classOfT)) {
            IntegerAdapter.write(this);
        } else if(long.class.isAssignableFrom(classOfT) || Long.class.isAssignableFrom(classOfT)) {
            LongAdapter.write(this);
        } else if(float.class.isAssignableFrom(classOfT) || Float.class.isAssignableFrom(classOfT)) {
            FloatAdapter.write(this);
        } else if(double.class.isAssignableFrom(classOfT) || Double.class.isAssignableFrom(classOfT)) {
            DoubleAdapter.write(this);
        } else if (Number.class.isAssignableFrom(classOfT)) {
            NumberAdapter.write(this);
        } else if (String.class.isAssignableFrom(classOfT)) {
            StringAdapter.write(this);
        } else if (Map.class.isAssignableFrom(classOfT)) {
            MapAdapter.write(this);
        } else if(Collection.class.isAssignableFrom(classOfT)) {
            CollectionAdapter.write(this);
        } else {
            ReflectiveAdapter.write(this);
        }
    }

    public String doWrite() throws AppJsonException {
        doWrite(this.object);
        return this.writer.toString();
    }
}
